package com.candy.service.impl;

import com.candy.dao.IAccountDao;
import com.candy.dao.impl.AccountDaoImpl;
import com.candy.service.IAccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.Date;

/**
 * 基于xml方式进行配置：
 * <bean id="AccountService" class="com.candy.service.impl.AccountSerivceImpl" scope="prototype"-->
 * init-method="initMethod" destroy-method="endMethod">
 *      <property name="name" value="李逍遥"></property>
 *</bean>
 *
 * 1、用户创建对象的：
 *         和xml配置方式中的bean标签的作用是一样的
 *         a、注解@Component
 *              作用：
 *              把资源让 spring 来管理。相当于在 xml 中配置一个 bean。
 *              属性：
 *              value：指定 bean 的 id。如果不指定 value 属性，默认 bean 的 id 是当前类的类名。首字母小写
 *         b、@Controller：一般用于表现层的注解。
 *         c、@Service：一般用于业务层的注解。
 *         d、@Repository：一般用于持久层的注解。
 *         他们三个注解都是针对一个的衍生注解，他们的作用及属性都是一模一样的。
 *         他们只不过是提供了更加明确的语义化。
 * 2、用于注入数据的：
 *        和xml配置方式中的property标签的作用是一样的
 *        a、@Autowired
 *        作用：
 *          自动按照类型注入。当使用注解注入属性时，set 方法可以省略。
 *          它只能注入其他 bean 类型。当有多个类型匹配时，
 *          使用要注入的对象变量名称作为 bean 的 id，
 *          在 spring 容器查找，找到了也可以注入成功。找不到就报错。
 *          b、Qualifier:
 *         作用：在按照类中注入的基础之上再按照名称注入。它在给类成员注入时不能单独使用。
 *         但是在给方法参数注入时可以
 *         属性：
 *          value：用于指定注入bean的id。
 *         c、Resource
 *         作用：直接按照bean的id注入。它可以独立使用
 *        属性：
 *         name：用于指定bean的id。
 *         以上三个注入都只能注入其他bean类型的数据，而基本类型和String类型无法使用上述注解实现。
 *          另外，集合类型的注入只能通过XML来实现。
 *          d、Value:
 *              作用：用于注入基本类型和String类型的数据
 *               属性：
 *                   value：用于指定数据的值。它可以使用spring中SpEL(也就是spring的el表达式）
 *                    SpEL的写法：${表达式}
 *
 * 3、指定对象的作用范围：
 *        和xml配置方式中的scope属性的作用是一样的
 *        作用：用于指定bean的作用范围
 *          属性：
 *              value：指定范围的取值。常用取值：singleton prototype
 *
 * 4、与生命周期相关的：
 *        和xml配置方式中的init-method、destroy-method属性的作用是一样的
 *      PreDestroy
 *          作用：用于指定销毁方法
 *      PostConstruct
 *          作用：用于指定初始化方法
 */
@Scope(value = "singleton")
@Repository(value = "accountService")
public class AccountSerivceImpl implements IAccountService {
    @Value("张三")
    private String name;
    private Integer age;
    private Date birthday;
//    @Autowired
//    @Qualifier(value ="accountDaoImpl")
//    @Resource(name = "accountDaoImpl")
    @Value("#{accountDaoImpl}")
    private IAccountDao accountDao;

    public AccountSerivceImpl() {
    }

    public AccountSerivceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }



    @Override
    public void saveAccount() {
        accountDao.saveAccount();
        System.out.println(name);

    }

@PostConstruct
    public void  initMethod(){
        System.out.println("对象初始化调用");
    }
@PreDestroy
    public void endMethod(){
        System.out.println("对象销毁时");
    }

    @Override
    public String toString() {
        return "AccountSerivceImpl{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", birthday=" + birthday +
                '}';
    }
}
